﻿using TravelServer.Models;
using TravelServer.DBContexs;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using TravelServer.DTOs;
using TravelServer.Helper;
using static Microsoft.Extensions.Logging.EventSource.LoggingEventSource;
using TravelServer.Dtos;

namespace TravelServer.Services
{
    public class TouristRouteRepository : ITouristRoutsRepository
    {
        private readonly APPDBContex dbContex;
        private readonly IPropertyMappingService propertyMappingService;
        public TouristRouteRepository(APPDBContex _appdbContex, IPropertyMappingService propertyMappingService)
        {
            this.dbContex = _appdbContex;
            this.propertyMappingService = propertyMappingService;
        }

        public async Task<TouristRoute> GetTouristRouteAsync(Guid touristRouteId)
        {

            return await dbContex.TouristRoutes.Include(t => t.TouristRoutePictures).FirstOrDefaultAsync(x => x.Id == touristRouteId);
        }

        public async Task<PageNationList<TouristRoute>> GetTouristRouteListAsync(string keyworld, string ratingOperator,
            int? ratingValue, int pageNumber, int pageSize,string orderBy)
        {
            IQueryable<TouristRoute> result = dbContex.TouristRoutes.Include(t => t.TouristRoutePictures);
            
            if (!string.IsNullOrWhiteSpace(keyworld))
            {
                keyworld = keyworld.Trim();
                result = result.Where(t => t.Title.Contains(keyworld));
            }
            if (ratingValue >= 0)
            {
                result = ratingOperator switch
                {
                    "largerThan" => result.Where(t => t.Rating >= ratingValue),
                    "lessThan" => result.Where(t => t.Rating <= ratingValue),
                    _ => result.Where(t => t.Rating == ratingValue),
                };
            }
           
            if (!string.IsNullOrWhiteSpace(orderBy))
            {
                var touristRouteMappingDictionary = propertyMappingService
                    .GetPropertyMapping<TouristRouteDto, TouristRoute>();

                result = result.ApplySort(orderBy, touristRouteMappingDictionary);
            }


            return await PageNationList<TouristRoute>.CreateFromFactory(pageNumber, pageSize, result);
        }

        public async Task<TouristRoutePictures> GetTouristRoutePicturesByPicturesIdAsync(int pictureId)
        {
            return await dbContex.TouristRoutePictures.Where(p => p.Id == pictureId).FirstOrDefaultAsync();
        }

        public async Task<IEnumerable<TouristRoutePictures>> GetTouristRoutePicturesByTouristRouteIdAsync(Guid touristRouteId)
        {
            return await dbContex.TouristRoutePictures.Where(t => t.TouristRouteId == touristRouteId).ToListAsync();
        }

        public async Task<bool> HasTouristRouteAsync(Guid touristRouteId)
        {
            return await dbContex.TouristRoutes.AnyAsync(t => t.Id == touristRouteId);
        }

        public void ADDTouristRoute(TouristRoute p)
        {
            if (p == null)
            {
                throw new ArgumentNullException(nameof(p));
            }
            this.dbContex.TouristRoutes.Add(p);
        }

        public async Task<bool> SaveDataAsync()
        {
            return await this.dbContex.SaveChangesAsync() > 0;
        }

        public void ADDTouristRoutePicture(Guid touristRouteId, TouristRoutePictures touristRoutePictures)
        {
            if (touristRouteId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(touristRouteId));
            }
            if (touristRoutePictures == null)
            {
                throw new ArgumentNullException(nameof(touristRoutePictures));
            }

            touristRoutePictures.TouristRouteId = touristRouteId;
            dbContex.TouristRoutePictures.Add(touristRoutePictures);


        }

        public void DeleteTouristRoute(TouristRoute p)
        {
            if (p == null)
            {
                throw new ArgumentNullException(nameof(p));
            }
            dbContex.TouristRoutes.Remove(p);
        }

        public void DeleteTouristRoutePicture(TouristRoutePictures touristRoutePictures)
        {
            if (touristRoutePictures == null)
            {
                throw new ArgumentNullException(nameof(touristRoutePictures));
            }

            dbContex.TouristRoutePictures.Remove(touristRoutePictures);
        }

        public void DeleteTourisRoutes(IEnumerable<TouristRoute> routes)
        {
            dbContex.TouristRoutes.RemoveRange(routes);
        }

        public async Task<IEnumerable<TouristRoute>> GetTourisRoutesAsync(IEnumerable<Guid> ids)
        {
            return await dbContex.TouristRoutes.Where(t => ids.Contains(t.Id)).ToListAsync();
        }

        public async Task<ShoppingCart> GetShoppingCartByUserIdAsync(string userId)
        {
            //include表示关联查询：语义解释，从ShoppingCarts表中，查询userId相等所有购物车数据
            //购物车数据需要包含属性中的s.user/s.ShoppingCartlineItems/item还需要包含i.TouristRoute
            return await dbContex.ShoppingCarts.
                Include(s => s.User)
                .Include(s => s.ShoppingCartlineItems).ThenInclude(i => i.TouristRoute)
                .Where(s => s.UserId == userId)
                .FirstOrDefaultAsync();
        }

        public async Task AddShoppingCartAsync(ShoppingCart shoppingCart)
        {
            await dbContex.ShoppingCarts.AddAsync(shoppingCart);
        }

        public async Task AddShoppingCartItemAsync(LineItem item)
        {
            await dbContex.LineItems.AddAsync(item);
        }

        public async Task<LineItem> GetShoppingCartItemAsync(int itemId)
        {
            return await dbContex.LineItems.Where(l => l.Id == itemId).FirstAsync();
        }

        public void DeleteShoppingCartItem(LineItem item)
        {
            dbContex.LineItems.Remove(item);
        }

        public async Task<IEnumerable<LineItem>> GetShoppingCartItemsByIdListAsync(IEnumerable<int> ids)
        {
            return await dbContex.LineItems.Where(l => ids.Contains(l.Id)).ToListAsync();
        }

        public void DeleteShoppingCartItems(IEnumerable<LineItem> items)
        {
            dbContex.LineItems.RemoveRange(items);
        }

        public async Task SaveOrderAsync(Order order)
        {
            await dbContex.Orders.AddAsync(order);

        }

        public async Task<Order> GetOrderByIdAsync(Guid orderId)
        {
            return await dbContex.Orders
                .Include(o => o.OrderLineItems).ThenInclude(l => l.TouristRoute)
                .Where(o => o.Id == orderId)
                .FirstOrDefaultAsync();

        }

        public async Task<PageNationList<Order>> GetOrdersByUserIdAsync(string userId, int pagenumber, int pagesize)
        {
            IQueryable<Order> result = dbContex.Orders
                .Include(o => o.OrderLineItems).ThenInclude(l => l.TouristRoute)
                .Where(o => o.UserId == userId);
             
            return await PageNationList<Order>.CreateFromFactory(pagenumber, pagesize,result);


        }
    }
}
